#include"Socket.h"
#include<cstring>
#include<unistd.h>
#include<fcntl.h>
#include<errno.h>
#include"error.h"


Socket::Socket(/* args */)
{
    fd_ = socket(AF_INET,SOCK_STREAM,0);
}
//客户端连接之后的
Socket::Socket(int fd)
{
    fd_ = fd;
    setNotBolcking();
}

void Socket::Bind(InetAddress *addr)
{
    struct sockaddr_in addr_in = addr->getAddr();
    printError(bind(fd_,(sockaddr*)&addr_in,sizeof(addr_in))==-1,"绑定错误") ;
}

void Socket::Listen()
{
    printError(listen(fd_,SOMAXCONN)==-1,"监听问题");
}

void Socket::setNotBolcking()
{
    fcntl(fd_,F_SETFL,fcntl(fd_,F_GETFL)|O_NONBLOCK);
}

bool Socket::isNonBolcking()
{
    return (fcntl(fd_,F_GETFL) & O_NONBLOCK) != 0;
}

int Socket::getFd()
{
    return fd_;
}

int Socket::Accept(InetAddress *addr)
{
    int clnt_fd = -1;
    struct sockaddr_in clnt_addr = addr->getAddr();
    socklen_t clnt_len = sizeof(clnt_addr);
    //判断是否为非阻塞模式
    if(isNonBolcking()){
        while (true)
        {
            clnt_fd = accept(fd_,(sockaddr*)&clnt_addr,&clnt_len);
            if(clnt_fd == -1 &&(errno == EAGAIN || errno == EWOULDBLOCK)){
                continue;
            }
            break;
        }
    }
    else{
        clnt_fd = accept(fd_,(sockaddr*)&clnt_addr,&clnt_len);
    }
    addr->setsockaddr(clnt_addr);
    return clnt_fd;
}

Socket::~Socket()
{
    if(fd_ != -1){
        close(fd_);
        fd_ = -1;
    } 
}



InetAddress::InetAddress(/* args */)
{
        memset(&addr_, 0, sizeof(addr_));
        addr_.sin_family = AF_INET;
        addr_.sin_addr.s_addr = INADDR_ANY;
        addr_.sin_port = 0;
}

InetAddress::InetAddress(const char *ip, uint16_t port)
{
    memset(&addr_,0,sizeof(addr_));
    addr_.sin_family = AF_INET;
    if (ip != nullptr) {
            addr_.sin_addr.s_addr = inet_addr(ip);
            if (addr_.sin_addr.s_addr == INADDR_NONE) {
                addr_.sin_addr.s_addr = INADDR_ANY;
            }
        } else {
            addr_.sin_addr.s_addr = INADDR_ANY;
        }
    addr_.sin_port = htons(port);
}

void InetAddress::setsockaddr(sockaddr_in addr)
{
    addr_ = addr;
}
const char *InetAddress::getIp() 
{
    return inet_ntoa(addr_.sin_addr);
}
uint16_t InetAddress::getPort()
{
    return ntohs(addr_.sin_port);
}
sockaddr_in InetAddress::getAddr()
{
    return addr_;
}
InetAddress::~InetAddress()
{
}